package com.moon.cloud.common.exception;

import com.moon.cloud.common.response.Response;
import com.moon.cloud.common.response.ResponseEntity;
import jakarta.servlet.http.HttpServletRequest;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpStatus;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.validation.BindException;
import org.springframework.validation.FieldError;
import org.springframework.web.HttpMediaTypeNotSupportedException;
import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.MissingServletRequestParameterException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.method.annotation.MethodArgumentTypeMismatchException;
import org.springframework.web.multipart.MaxUploadSizeExceededException;
import org.springframework.web.servlet.NoHandlerFoundException;

import java.nio.file.AccessDeniedException;
import java.sql.SQLException;
import java.util.stream.Collectors;

/**
 * 全局异常处理器
 */
@Slf4j
@RestControllerAdvice
public class GlobalExceptionHandler {

    /**
     * 处理自定义业务异常
     */
    @ExceptionHandler(MoonException.class)
    public ResponseEntity<Object> handleMoonException(MoonException e, HttpServletRequest request) {
        log.error("业务异常: {} - URI: {}", e.getMessage(), request.getRequestURI(), e);
        return Response.fail(e.getErrorCode(), e.getMessage());
    }

    /**
     * 处理参数校验异常（@Valid）
     */
    @ExceptionHandler(MethodArgumentNotValidException.class)
    public ResponseEntity<Object> handleMethodArgumentNotValidException(MethodArgumentNotValidException e, HttpServletRequest request) {
        String errors = e.getBindingResult().getFieldErrors().stream()
                .map(FieldError::getDefaultMessage)
                .collect(Collectors.joining(", "));
        log.error("参数校验异常: {} - URI: {}", errors, request.getRequestURI());
        return Response.fail(HttpStatus.BAD_REQUEST.value(), "参数校验失败: " + errors);
    }

    /**
     * 处理参数绑定异常（@Valid）
     */
    @ExceptionHandler(BindException.class)
    public ResponseEntity<Object> handleBindException(BindException e, HttpServletRequest request) {
        String errors = e.getBindingResult().getFieldErrors().stream()
                .map(FieldError::getDefaultMessage)
                .collect(Collectors.joining(", "));
        log.error("参数绑定异常: {} - URI: {}", errors, request.getRequestURI());
        return Response.fail(HttpStatus.BAD_REQUEST.value(), "参数绑定失败: " + errors);
    }

    /**
     * 处理缺少请求参数异常
     */
    @ExceptionHandler(MissingServletRequestParameterException.class)
    public ResponseEntity<Object> handleMissingServletRequestParameterException(MissingServletRequestParameterException e, HttpServletRequest request) {
        log.error("缺少请求参数: {} - URI: {}", e.getParameterName(), request.getRequestURI());
        return Response.fail(HttpStatus.BAD_REQUEST.value(), "缺少必要参数: " + e.getParameterName());
    }

    /**
     * 处理参数类型不匹配异常
     */
    @ExceptionHandler(MethodArgumentTypeMismatchException.class)
    public ResponseEntity<Object> handleMethodArgumentTypeMismatchException(MethodArgumentTypeMismatchException e, HttpServletRequest request) {
        log.error("参数类型不匹配: {} - URI: {}", e.getName(), request.getRequestURI());
        return Response.fail(HttpStatus.BAD_REQUEST.value(), "参数类型错误: " + e.getName());
    }

    /**
     * 处理请求方法不支持异常
     */
    @ExceptionHandler(HttpRequestMethodNotSupportedException.class)
    public ResponseEntity<Object> handleHttpRequestMethodNotSupportedException(HttpRequestMethodNotSupportedException e, HttpServletRequest request) {
        log.error("请求方法不支持: {} - URI: {}", e.getMethod(), request.getRequestURI());
        return Response.fail(HttpStatus.METHOD_NOT_ALLOWED.value(), "不支持的请求方法: " + e.getMethod());
    }

    /**
     * 处理媒体类型不支持异常
     */
    @ExceptionHandler(HttpMediaTypeNotSupportedException.class)
    public ResponseEntity<Object> handleHttpMediaTypeNotSupportedException(HttpMediaTypeNotSupportedException e, HttpServletRequest request) {
        log.error("媒体类型不支持: {} - URI: {}", e.getContentType(), request.getRequestURI());
        return Response.fail(HttpStatus.UNSUPPORTED_MEDIA_TYPE.value(), "不支持的媒体类型: " + e.getContentType());
    }

    /**
     * 处理请求体不可读异常
     */
    @ExceptionHandler(HttpMessageNotReadableException.class)
    public ResponseEntity<Object> handleHttpMessageNotReadableException(HttpMessageNotReadableException e, HttpServletRequest request) {
        log.error("请求体不可读 - URI: {}", request.getRequestURI(), e);
        return Response.fail(HttpStatus.BAD_REQUEST.value(), "请求体格式错误");
    }

    /**
     * 处理404异常
     */
    @ExceptionHandler(NoHandlerFoundException.class)
    public ResponseEntity<Object> handleNoHandlerFoundException(NoHandlerFoundException e, HttpServletRequest request) {
        log.error("接口不存在: {} - Method: {}", request.getRequestURI(), e.getHttpMethod());
        return Response.fail(HttpStatus.NOT_FOUND.value(), "接口不存在: " + request.getRequestURI());
    }

    /**
     * 处理空指针异常
     */
    @ExceptionHandler(NullPointerException.class)
    public ResponseEntity<Object> handleNullPointerException(NullPointerException e, HttpServletRequest request) {
        log.error("空指针异常 - URI: {}", request.getRequestURI(), e);
        return Response.fail(HttpStatus.INTERNAL_SERVER_ERROR.value(), "系统内部错误: 空指针异常");
    }

    /**
     * 处理非法参数异常
     */
    @ExceptionHandler(IllegalArgumentException.class)
    public ResponseEntity<Object> handleIllegalArgumentException(IllegalArgumentException e, HttpServletRequest request) {
        log.error("非法参数异常: {} - URI: {}", e.getMessage(), request.getRequestURI());
        return Response.fail(HttpStatus.BAD_REQUEST.value(), "参数错误: " + e.getMessage());
    }

    /**
     * 处理非法状态异常
     */
    @ExceptionHandler(IllegalStateException.class)
    public ResponseEntity<Object> handleIllegalStateException(IllegalStateException e, HttpServletRequest request) {
        log.error("非法状态异常: {} - URI: {}", e.getMessage(), request.getRequestURI());
        return Response.fail(HttpStatus.INTERNAL_SERVER_ERROR.value(), "系统状态错误: " + e.getMessage());
    }

    /**
     * 处理数组越界异常
     */
    @ExceptionHandler(ArrayIndexOutOfBoundsException.class)
    public ResponseEntity<Object> handleArrayIndexOutOfBoundsException(ArrayIndexOutOfBoundsException e, HttpServletRequest request) {
        log.error("数组越界异常 - URI: {}", request.getRequestURI(), e);
        return Response.fail(HttpStatus.INTERNAL_SERVER_ERROR.value(), "系统内部错误: 数组越界");
    }

    /**
     * 处理数字格式异常
     */
    @ExceptionHandler(NumberFormatException.class)
    public ResponseEntity<Object> handleNumberFormatException(NumberFormatException e, HttpServletRequest request) {
        log.error("数字格式异常 - URI: {}", request.getRequestURI(), e);
        return Response.fail(HttpStatus.BAD_REQUEST.value(), "数字格式错误");
    }

    /**
     * 处理类型转换异常
     */
    @ExceptionHandler(ClassCastException.class)
    public ResponseEntity<Object> handleClassCastException(ClassCastException e, HttpServletRequest request) {
        log.error("类型转换异常 - URI: {}", request.getRequestURI(), e);
        return Response.fail(HttpStatus.INTERNAL_SERVER_ERROR.value(), "系统内部错误: 类型转换失败");
    }

    /**
     * 处理数据库异常
     */
    @ExceptionHandler(SQLException.class)
    public ResponseEntity<Object> handleSQLException(SQLException e, HttpServletRequest request) {
        log.error("数据库异常 - URI: {}", request.getRequestURI(), e);
        return Response.fail(HttpStatus.INTERNAL_SERVER_ERROR.value(), "数据库操作失败");
    }

    /**
     * 处理访问拒绝异常
     */
    @ExceptionHandler(AccessDeniedException.class)
    public ResponseEntity<Object> handleAccessDeniedException(AccessDeniedException e, HttpServletRequest request) {
        log.error("访问拒绝: {} - URI: {}", e.getMessage(), request.getRequestURI());
        return Response.fail(HttpStatus.FORBIDDEN.value(), "访问被拒绝: " + e.getMessage());
    }

    /**
     * 处理文件上传大小超限异常
     */
    @ExceptionHandler(MaxUploadSizeExceededException.class)
    public ResponseEntity<Object> handleMaxUploadSizeExceededException(MaxUploadSizeExceededException e, HttpServletRequest request) {
        log.error("文件大小超限 - URI: {}", request.getRequestURI());
        return Response.fail(HttpStatus.BAD_REQUEST.value(), "上传文件大小超出限制");
    }

    /**
     * 处理算术异常（如除零）
     */
    @ExceptionHandler(ArithmeticException.class)
    public ResponseEntity<Object> handleArithmeticException(ArithmeticException e, HttpServletRequest request) {
        log.error("算术异常 - URI: {}", request.getRequestURI(), e);
        return Response.fail(HttpStatus.INTERNAL_SERVER_ERROR.value(), "系统内部错误: 算术运算异常");
    }

    /**
     * 处理运行时异常
     */
    @ExceptionHandler(RuntimeException.class)
    public ResponseEntity<Object> handleRuntimeException(RuntimeException e, HttpServletRequest request) {
        log.error("运行时异常 - URI: {}", request.getRequestURI(), e);
        return Response.fail(HttpStatus.INTERNAL_SERVER_ERROR.value(), "系统运行异常: " + e.getMessage());
    }

    /**
     * 处理所有未捕获的异常
     */
    @ExceptionHandler(Exception.class)
    public ResponseEntity<Object> handleException(Exception e, HttpServletRequest request) {
        log.error("未知异常 - URI: {}", request.getRequestURI(), e);
        return Response.fail(HttpStatus.INTERNAL_SERVER_ERROR.value(), "系统异常，请联系管理员");
    }
}
